<?php
/**
 * @author James R Hartford
 * @package jphpframework
 * @abstract provide some simple abstration to make coding simpler and
 * more secure
 *
 * class JController
 * class JCrypt
 * class JDb
 * class JDbResult
 * class JDbTable
 * class JFeed
 * class JTemplate
 * class Utils
 */

class JController{

    private $config;
    private $params;

    function __construct($config = null, $path = null)
    {
        $this->config = $config;

        $findQ = strpos($_SERVER['REQUEST_URI'], "?");
        if($findQ)
        	$uri = substr($_SERVER['REQUEST_URI'], 0, $findQ);
        else
        	$uri = $_SERVER['REQUEST_URI'];

        $uri = str_replace("http://", "", $uri);
        $uri = str_replace("https://", "", $uri);
        $uri = str_replace($_SERVER['SERVER_NAME'],"",$uri);
        $uri = trim(str_replace($path, "", $uri), "/");

        $tmpparams = explode("/", $uri);

        $configcount = count($this->config);
        $paramcount = count($tmpparams);

        for($i = 0; $i < $configcount && $paramcount > 0; $i++){
            $params[$this->config[$i]] = $tmpparams[$i];
        }

        for($i = $configcount; $i < count($tmpparams); $i++){
            $params[$tmpparams[$i]] = $tmpparams[++$i];
        }

        $this->params = $params;
    }

    public function getParam($param)
    {
        return $this->params[$param];
    }

    public function toString()
    {
        ob_start();
        print_r($this->params);
        return ob_get_clean();
    }

    public function output(){
        echo "<pre>";
        print_r($this->params);
        echo "</pre>";
    }
}

class JCrypt{

	 /**
     * Jblowfish constructor
     * Initializes the JCrypt object, and gives a sets
     * the secret key
     *
     * @access public
     */
	function __construct(){
		$this->key = JCRYPT_KEY;
	}


	 /**
     * Encrypts a string
     *
     * @param string $data
     * @return string returns encrypted text
     * @access public
     */
	function encrypt($data){
		if($data == ''){
			return '';
		}else{
			$td = MCRYPT_BLOWFISH;
			$iv_size = mcrypt_get_iv_size($td, MCRYPT_MODE_ECB);
			$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
			$encrypted_data = bin2hex(mcrypt_encrypt($td, $this->key, $data, MCRYPT_MODE_ECB, $iv));
			return $encrypted_data;
		}
	}

	/**
     * Decrypts an encrypted string
     *
     * @param string $data
     * @return string returns plain text
     * @access public
     */
	function decrypt($data){
		if($data == ''){
			return '';
		}else{
			$td = MCRYPT_BLOWFISH;
			$iv_size = mcrypt_get_iv_size($td, MCRYPT_MODE_ECB);
			$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
			for( $i = 0; $i < strlen( $data ); $i += 2 )
			eval( '$decrypt .= "\x' . substr( $data, $i, 2 ) . '";' );

			$decrypted_data = mcrypt_decrypt($td, $this->key, $decrypt, MCRYPT_MODE_ECB, $iv);
			$decrypted_data = rtrim($decrypted_data, "\0");
			return $decrypted_data;
		}
	}
}

class JDb
{
    public $db;
    public $fetchmode;
    public $dbtype;
	public $connectfunc;
	public $queryfunc;
	public $errorfunc;
	public $closefunc;

    function __construct($params)
    {
    	$this->dbtype = strtolower($params['dbtype']);
        $this->fetchmode = MYSQL_ASSOC;

		$this->connectfunc = $this->dbtype."_connect";
		$this->queryfunc = $this->dbtype."_query";
    	$this->errorfunc = $this->dbtype."_error";
    	$this->closefunc = $this->dbtype."_close";

    	$tmp = $this->connectfunc;
		$this->db = $tmp($params['host'], $params['username'], $params['password'], $params['database']);
    }


    public function exec($query, $values = null)
    {
        $query = $this->createSelectStatement($query, $values);
        $result = $this->query($query);
        return ($result)?true:false;
    }


    public function select($query, $values = null)
    {
        $query = $this->createSelectStatement($query, $values);
        $result = $this->query($query);
        $result = new JDbResult($result, $this->dbtype,$this->fetchmode);
		return ($result)?$result:null;
    }


    public function selectAll($query, $values = null)
    {
        $result = $this->select($query, $values);
        while($row = $result->fetchRow())
            $tmp[] = $row;
        return $tmp;
    }


	public function selectList($query, $values = null)
	{
		$ListArray = array();
		$result = $this->select($query, $values);

		while($row = $result->fetchRow()){
		    $row = array_values($row);
		    $index = $row[0];
		    $row[0] = null;
		    $ListArray[$index] =   trim(implode(" ", $row));
		}

		return $ListArray;
	}

    public function selectCol($query, $column, $values = null){
        $res = $this->select($query, $values);

        while($row = $res->fetchRow()){
        	$col[] = $row[$column];
        }
        return $col;
    }


    public function cleanData($data)
    {
	    if(is_array($data))array_walk($data, array($this, 'clean'));
	    return $data;
	}


	public function showTables()
	{
    	$tmp = $this->fetchmode;
    	$this->fetchmode = MYSQL_BOTH;

    	switch($this->dbtype){
           case 'mysqli':
           case 'mysql':
	           $query = "Show Tables";
	           break;
           case 'mssql':
               $query = "select TABLE_NAME as tblname from information_schema.tables";
	           break;
           default:
               break;
        }

        $res =& $this->select($query);
        while($row =& $res->fetchRow()){
        	$tables[] = $row[0];
        }
        $this->fetchmode = $tmp;
        return $tables;
    }


    public function toString()
    {
    	return $this->_lastquery;
    }


    public function output()
    {
        echo $this->_lastquery;
    }


    public function setFetchMode($mode)
    {
        $this->fetchmode = $mode;
    }

    public function setCommitMode($mode=true)
    {
		mysqli_autocommit($this->db, $mode);
    }

	public function commit()
	{
		$this->db->commit();
    }

    public function rollback(){
      $this->db->rollback();
    }

    private function clean(&$value){
        switch($this->dbtype){
           case 'mysqli':
	           $value = mysqli_real_escape_string($this->db, $value);
	           break;
	       case 'mysql':
	           $value = mysql_real_escape_string($value, $this->db);
	           break;
           case 'mssql':
               $value = str_replace("'", "''", $value);
	           break;
           default:
               break;
        }
    }

    private function query($query)
    {
        $tmp = $this->queryfunc;
    	$result = $tmp($this->db, $query);

    	$tmp = $this->errorfunc;
        if($tmp($this->db) && ini_get('display_errors') == true)
        	die("<br><b>".strtoupper($this->dbtype)." ERROR:</b>".$tmp($this->db)."<br><b>QUERY:</b>".$query);

        $this->_lastquery = $query;
        return ($result)?$result:false;
    }

    private function createSelectStatement($query, $values = null)
    {
        if(is_array($values)){
            $values = $this->cleanData($values);
            foreach($values as $value)
                $query = substr_replace($query, $value, strpos($query, '?'), 1);
        }
        return $query;
    }
    
    public function close(){
    	$tmp = $this->closefunc;
    	$tmp($this->db);
    }

    function __destruct(){
    	$this->close();
    }
}

class JDbResult{

    var $result;
    var $dbtype;
    var $modetype;

    public function __construct($result, $dbtype, $modetype){
        $this->result = $result;
        $this->dbtype = $dbtype;
        $this->modetype = $modetype;
    }

    public function fetchRow($escape = false){
        switch($this->dbtype){
            case 'mysqli':
                $output = mysqli_fetch_array($this->result,$this->modetype);
                break;
            case 'mysql':
            	$output = mysql_fetch_array($this->result,$this->modetype);
                break;
            case 'mssql':
            	$output = mssql_fetch_array($this->result,$this->modetype);
                break;

        }

        if($escape == true && is_array($output)){
        	foreach($output as $key => $value){
        		$output[$key] = htmlentities($value);
        	}
        }
        return $output;
    }

    public function numRows(){

        switch($this->dbtype){
            case 'mysqli':
                return mysqli_num_rows($this->result);
                break;
        }
    }
}

class JDbTable{
	public $_primary;
	public $_primaryvalue;
	public $_table;
	public $_db;
	public $data;


	function __construct($db, $table, $primary, $primaryvalue = null){
	    $this->_db = $db;
		$this->_table = $table;
		$this->_primary = $primary;
		$this->modify($primaryvalue);
	}

	public function insert(){
	    $this->data = $this->_db->cleanData($this->data);

	    $query = "INSERT INTO ".$this->_table." ".
	    "( ".implode(",",array_keys($this->data))." ) ".
	    "VALUES ('".implode("','",$this->data)."')";
		$res = $this->_db->exec($query);

		if(!$res){
		    error_log("JDbTable ERROR");
			return false;
		}else{
			return $this->lastID();
		}
	}

	public function update(){
	    $this->data = $this->_db->cleanData($this->data);

        $query = "UPDATE ".$this->_table." SET ";

		foreach($this->data as $key => $value){
	        $query .= $key . "='".$value."', ";
	    }

	    $query = substr($query,0,strlen($query) - 2);
		$query .= " WHERE ".$this->_primary."='".$this->_primaryvalue."'";

		$res = $this->_db->exec($query);

		if(!$res){
		    error_log("JDbTable ERROR: ".$res->getDebugInfo());
			return false;
		}else{
			return $this->_primaryvalue;
		}
	}

	public function save(){
	    if($this->_primaryvalue != null){
	        return $this->update();
	    }else{
	        return $this->insert();
	    }
	}

	public function lastId(){

	    switch($this->_db->dbtype){
	        case 'mysqli':
	        case 'mysql':
	            $query = "SELECT LAST_INSERT_ID() AS last_id";
	            break;
	        case 'mssql':
	            $query = "SELECT @@identity AS last_id";
	            break;
	        default:
	            $query = "SELECT " . $this->_primary . "
                FROM " . $this->_table . "
                ORDER BY " . $this->_primary . " DESC";
        	    $res = $this->_db->select($query);
        	    $row = $res->fetchRow();
        	    $last_id = $row[$this->_primary];
        	    break;
	    }

	    if(!$last_id){
    	    $res = $this->_db->select($query);
            $row = $res->fetchRow();
            $last_id = $row['last_id'];
	    }

	    return $last_id;
	}

	public function output(){
		echo $this->_db->_lastquery;
	}

	public function getRow($escape = false){
	    $query = "SELECT * FROM ".$this->_table.
	    " WHERE " . $this->_primary . "='".$this->_primaryvalue."'";
	    $res =& $this->_db->select($query);
	    return $res->fetchRow($escape);
	}

	public function setId($value){
	    $this->_primaryvalue = $value;
	}

    protected function modify($key){
	    if(strlen(trim($key)) > 0){
	       $this->_primaryvalue = $key;
	    }
	}


	public function scaffold(){

	    if($_GET['do'] == 'edit'){

	        $form = new JForm($this->_table, 'post', "?".$_SERVER['QUERY_STRING']);

	        if(Utils::isVal($_GET['who'])){

	            $query = "SELECT * FROM ".$this->_table." WHERE ".$this->_primary."='?'";
	            $res =& $this->_db->select($query, array($_GET['who']));
	            if($res->numRows() > 0){
	                $row =& $res->fetchRow();
	                $form->setdefaults($row);
	            }
	        }


	        $cquery = "SHOW COLUMNS FROM ?";
	        $res =& $this->_db->select($cquery, array($this->_table));
	        while($row =& $res->fetchRow()){
	            $info = explode("(", $row['Type']);
	            $info2 = explode(")", $info[1]);
	            $type = $info[0];
	            $size = $info2[0];

	            if(in_array($type, array('char','varchar', 'int', 'tinyint', 'smallint', 'mediumint', 'bigint',)) && $row['Key'] != "PRI"){
	                $form->addelement('text', $row['Field'], $row['Field']);
	                $form->addrule($row['Field'], "You can only enter ".$size." characters", 'maxlength', $size);
	            }else if(in_array($type, array('text', 'tinytext','blob', 'tinyblob','mediumblob'))){
	                $form->addelement('textarea', $row['Field'], $row['Field'], array('style'=>'width:250px;height:150px;'));
	            }else if(in_array($type, array('date'))){
	                $form->addelement('date', $row['Field'], $row['Field'], array('format'=>"m-d-Y"));
	            }else if(in_array($type, array('datetime'))){
	                $form->addelement('date', $row['Field'], $row['Field'], array('format'=>"m-d-Y h:i A"));
	            }else if(in_array($type, array('enum'))){
	                $vals = explode(",",$size);
	                foreach($vals as $key => $value){
	                    $tmp = substr($value, 1, strlen($value) - 2);
	                    $nvals[$tmp] = $tmp;
	                }
	                $form->addelement('select', $row['Field'], $row['Field'], $nvals);
	            }
	        }

	        $form->addelement('submit', 'save', 'Save');

	        if($form->validate()){

	            $tbl = new JDbTable($this->_db, $this->_table, $this->_primary, $_GET['who']);
	            $res =& $this->_db->select($cquery, array($this->_table));
	            while($row =& $res->fetchRow()){
	                if($row['Key'] != "PRI"){
    	                if(in_array($row['Type'], array('date'))){
    	                    $tbl->data[$row['Field']] = $_POST[$row['Field']]['Y']."-".$_POST[$row['Field']]['m']."-".$_POST[$row['Field']]['d'];
    	                }else if(in_array($row['Type'], array('datetime'))){
    	                    $tbl->data[$row['Field']] = $_POST[$row['Field']]['Y']."-".$_POST[$row['Field']]['m']."-".$_POST[$row['Field']]['d']." ".Utils::timeto24Hour($_POST[$row['Field']]['h'],$_POST[$row['Field']]['i'],$_POST[$row['Field']]['A']);
    	                }else{
    	                    $tbl->data[$row['Field']] = $_POST[$row['Field']];
    	                }
	                }
	            }

	            if($tbl->save()){
	               header("Location: ?saved=true");
	            }else{
	               header("Location: ?saved=false");
	            }
	            exit;
	        }

	        $tmp = $form->toHtml();

	    }else{
	        $query = "SELECT * FROM ".$this->_table." ORDER BY ".$this->_primary." ASC";
    	    $res =& $this->_db->select($query);

    	    if($res->numRows() > 0){
    	        if($_GET['saved'] == 'true'){
    	           $tmp .= "<h1>Item was saved</h1>";
    	        }else if($_GET['saved'] == 'false'){
    	           $tmp .= "<h1>Error saving item</h1>";
    	        }

    	        $tmp .= "<a href='?do=edit'>Add New</a><br />
    	        <table>";

    	        for($i = 0;$row =& $res->fetchRow(); $i++){

    	            if($i == 0){
    	                $tmp .= "<tr>";
    	                $heads = array_keys($row);
    	                foreach($heads as $head){
    	                    $tmp .= "<th>".$head."</th>";
    	                }
    	                $tmp .= "<th></th></tr>";
    	            }
    	            $tmp .= "<tr>";
    	            foreach($row as $key => $value){
    	                $tmp .= "<td>".$value."</td>";
    	            }
    	            $tmp .= "<td><a href='?do=edit&who=".$row[$this->_primary]."'>Edit</a></td>";
    	            $tmp .= "</tr>";
    	        }
    	        $tmp .= "</table>";
    	    }
	    }

	    return $tmp;
	}
}

class JFeed
{
    public $title;
    public $link;
    public $description;
    public $language;
    public $pubDate;
    public $lastBuildDate;
    public $docs;
    public $generator;
    public $managingEditor;
    public $webMaster;
    public $items;

    public function addItem($title,$link,$desc,$pubDate,$guid){
        $this->items[] = array('title'=>$title,
                         'link'=>$link,
                         'description'=>$desc,
                         'pubDate'=>$pubDate,
                         'guid'=>$guid);
    }

    public function toRSS2_0()
    {
    	$rss = new SimpleXMLElement("<rss version=\"2.0\"></rss>");
    	$feed = $rss->addChild('channel');
		$feed->addChild('title', $this->title);
		$feed->addChild('link', $this->link);
		$feed->addChild('description', $this->description);
		$feed->addChild('language', $this->language);
		$feed->addChild('pubDate', $this->pubDate);
		$feed->addChild('lastBuildDate', $this->lastBuildDate);
		$feed->addChild('docs', $this->docs);
		$feed->addChild('generator', $this->generator);
		$feed->addChild('managingEditor', $this->managingEditor);
		$feed->addChild('webMaster', $this->webMaster);

        foreach($this->items as $item){
			$itemx = $feed->addChild('item');
			$itemx->addChild('title', $item['title']);
			$itemx->addChild('link', $item['link']);
			$itemx->addChild('description', $item['description']);
			$itemx->addChild('pubDate', $item['pubDate']);
			$itemx->addChild('guid', $item['guid']);

        }
        return $rss->asXML();
    }
}

class JForm{

	public $formname;
	public $method;
	public $action;
	public $elements = array();
	public $defaults = array();
    public $formTemplate;
    public $elementTemplate;

	public function __construct($formname = 'JForm', $method='POST', $action=null)
	{
		$this->formname = $formname;
		$this->method = $method;
		$this->action = ($action == null)?$_SERVER['PHP_SELF']:$action;

		$this->setFormTemplate("<fieldset><legend>\$this->formname</legend>".
		"<form name='\$this->formname' method='\$this->method' action='\$this->action'>\n".
		"<input type='hidden' name='formname' value='\$this->formname'/>".
		"<table>\$this->elements</table>\n".
		"</form>\n</fieldset>\n");

		$this->setElementTemplate("<tr valign='top'><td>\$this->label</td><td><div style='color:#f00;'>\$this->error</div> \$this->element</td></tr>");
	}

	public function setFormTemplate($val)
	{
	    $this->formTemplate = $val;
	}

	public function setElementTemplate($val, $element = null)
	{
	    if(Utils::isVal($element)){
	        $this->templates[$element] = $val;
	    }else{
	        $this->elementTemplate = $val;
	    }
	}

	public function getElementTemplate($element)
	{
        return (Utils::isVal($this->templates[$element]))?$this->templates[$element]:$this->elementTemplate;
	}

	public function setDefaults($defaults)
	{
		$this->defaults = $defaults;
	}

	public function addelement($type, $varname, $label, $label2 = null, $options = null)
	{
	    if(is_array($label2))
		   $this->elements[$varname] = array('type'=>$type, 'label'=>$label, 'options'=>$label2);
	    else
	       $this->elements[$varname] = array('type'=>$type, 'label'=>$label, 'label2'=>$label2, 'options'=>$options);
	}


	public function addrule($varname, $message, $type, $extra='', $more='')
	{
		$this->rules[$varname][] = array('message'=>$message, 'type'=>$type, 'extra'=>$extra);
	}

	public function validate()
	{
		$process = true;

		if($_POST['formname'] == $this->formname){
			$this->defaults = $_POST;

			foreach($this->rules as $varname => $rule){
			    foreach($rule as $values){

    				if($values['type'] == 'required'){
    					if(!Utils::isVal($_POST[$varname])){
    						$process = false;
    						$this->elements[$varname]['message'] = $values['message'];

    					}
    				}else if($values['type'] == 'maxlength'){
    				    if(strlen($_POST[$varname]) > $values['extra']){
    				        $process = false;
    				        $this->elements[$varname]['message'] = $values['message'];
    				    }
    				}

    			}
			}
		}else{
			$process = false;
		}

		return $process;
	}

	public function toHtml()
	{
		foreach($this->elements as $varname => $values)
		{
		    $extra = '';
		    $elem = new JTemplate();
		    $elem->assign('label', $values['label']);
		    $elem->assign('error', $values['message']);

			$options = '';
		    if(is_array($values['options'])){
    		    foreach($values['options'] as $option => $value){
    		        $options .= " $option='$value'";
    		    }
		    }

		    switch($values['type']){
		        case 'date':
		        case 'text':
		        	if(is_array($this->rules[$varname])){
			            foreach($this->rules[$varname] as $rule){
	    		            if($rule['type'] == 'maxlength'){
	    		                $extra = " maxlength='{$rule['extra']}'";
	    		            }
			            }
		        	}
		            $elem->assign('element', "<input type='text' name='".$varname."' value='".$this->defaults[$varname]."' $extra/>");
		            break;
		        case 'password':
		            if(is_array($this->rules[$varname])){
		                foreach($this->rules[$varname] as $rule){
        		            if($rule['type'] == 'maxlength'){
        		                $extra = " maxlength='{$rule['extra']}'";
        		            }
    		            }
		            }
		            $elem->assign('element', "<input type='password' name='".$varname."' value='".$this->defaults[$varname]."' $extra/>");
		            break;
		        case 'textarea':
		            $elem->assign('element', "<textarea name='".$varname."'>".$this->defaults[$varname]."</textarea>");
		            break;
		        case 'checkbox':
		            $elem->assign('element', "<input type='checkbox' name='".$varname."' id='jform_{$varname}' value='".$this->defaults[$varname]."'><label for='jform_".$varname."' >{$values['label2']}</label></input>");
		            break;
		        case 'radio':
		            $elem->assign('element', "<input type='radio' name='".$varname."' id='jform_{$varname}' value='".$this->defaults[$varname]."'><label for='jform_".$varname."' >{$values['label2']}</label></input>");
		            break;
		        case 'select':

		            foreach($values['options'] as $key => $value){
		                if($key == $this->defaults[$varname])
		                    $opts .= "<option value='{$key}' selected='selected'>{$value}</option>";
		                else
		                    $opts .= "<option value='{$key}'>{$value}</option>";
		            }


		            $elem->assign('element', "<select name='".$varname."'>{$opts}</select>");
		            break;
		        case 'file':
		            $elem->assign('label', '');
		            $elem->assign('element', "<input type='file' name='".$varname."' />");
		            break;
		        case 'submit':
		            $elem->assign('label', '');
		            $elem->assign('element', "<input type='submit' name='".$varname."' value='".$values['label']."' />");
		            break;
		        case 'button':
		            $elem->assign('label', '');
		            $elem->assign('element', "<input type='button' name='".$varname."' value='".$values['label']."' />");
		            break;
		        default:
		            $elem->assign('element', "");
		            break;
		    }

		    $elements .= $elem->fetch($this->getElementTemplate($varname));
		}

		$html = new JTemplate();
		$html->assign('formname', $this->formname);
		$html->assign('method', $this->method);
		$html->assign('action', $this->action);
		$html->assign('elements', $elements);
		$tmp = $html->fetch($this->formTemplate);

		return $tmp;
	}

}

class JTemplate{

	public $templatePath;

	public function __construct($path = null){
		$this->templatePath = $path;
	}

	public function assign($var, $value){
		$this->$var = $value;
	}

	public function append($var, $value){
		$this->$var .= $value;
	}

	public function arrayassign($array){
	    foreach($array as $key => $value){
	        $this->$key = $value;
	    }
	}

	public function display($file){
        include($this->templatePath.$file);
	}

	public function fetch($file){
		ob_start();
		$this->display($file);
		return ob_get_clean();
	}

}


class Utils{

    public static function isVal($val)
    {
        return (strlen(trim($val)) > 0)?true:false;
    }

    public static function timeto24Hour($hour=0,$min=0,$pm="PM")
    {
        if($pm == "PM")
            if($hour<12)
                $hour += 12;
            if(strlen($hour) < 2)
                $hour ="0".$hour;
            if(strlen($min) < 2)
                $min ="0".$min;

        return $hour.":".$min.":00";
    }

    public static function printR($what){
		echo "<pre>";
		print_r($what);
		echo "</pre>";
	}

	public static function displaydate($date, $format = null)
	{
		if(self::isVal($date) && $date != "0000-00-00" && $date != "0000-00-00 00:00:00"){
			if(self::isVal($format)){
				return date($format, strtotime($date));
			}else if(self::isVal(DATE_FORMAT)){
				return date(DATE_FORMAT, strtotime($date));
			}else{
				return date("m/d/Y", strtotime($date));
			}
		}else{
			return "N/A";
		}
	}

	public static function displaytime($date, $format = null)
	{
		if(self::isVal($date) && $date != "0000-00-00" && $date != "0000-00-00 00:00:00"){
			if(self::isVal($format)){
				return date($format, strtotime($date));
			}else if(self::isVal(TIME_FORMAT)){
				return date(TIME_FORMAT, strtotime($date));
			}else{
				return date("h:iA", strtotime($date));
			}
		}else{
			return "N/A";
		}
	}

	public static function arrayColumn($array, $column, $index = null){

		$arraycount = count($array);

		if(self::isVal($index)){
			for($i = 0; $i < $arraycount; $i++){
				$tmp[$array[$i][$index]] = $array[$i][$column];
			}
		}else{
			for($i = 0; $i < $arraycount; $i++){
				$tmp[] = $array[$i][$column];
			}
		}

		return $tmp;
	}

	public static function arrayJoin($a1, $a2, $a3=null, $a4=null, $a5=null, $a6=null, $a7=null, $a8=null, $a9=null, $a10=null) {
	   $a=array();
	   foreach($a1 as $key=>$value) $a[$key]=$value;
	   foreach($a2 as $key=>$value) $a[$key]=$value;
	   if (is_array($a3)) $a=self::arrayJoin($a,$a3,$a4,$a5,$a6,$a7,$a8,$a9,$a10);
	   return $a;
	}

}